﻿using System;
using System.Collections.Generic;
using Framework.Resource;
using Unity.VisualScripting;
using UnityEngine;
using Object = System.Object;

namespace Framework
{

    public partial class UIManager : FrameworkComponent
    {
        [SerializeField]
        private UIGroupInfo[] GroupInfos;
        
        [SerializeField]
        private Transform UIRoot;

        public float ExpireTime=60f;
        public float AutoReleaseTime=10f;
        
        private ResourceManager m_ResourceManager;
        /// <summary>
        /// 用于创建UIForm
        /// </summary>
        private UIFormHelper m_UIFormHelper;
        private int m_Serial;

       
        
        private Dictionary<int, string> m_UIFormsBeingLoaded;
        private List<int> m_UIFormsToReleaseOnLoad;

        private ObjectPool<UIFormInstanceObject> m_InstancePool;
        private Queue<IUIForm> m_RecycleQueue;
        private Dictionary<string, UIGroup> m_UIGroups;
        


        public UIManager()
        {
            m_UIFormsBeingLoaded = new Dictionary<int, string>();
            m_UIFormsToReleaseOnLoad = new List<int>();
            m_UIGroups = new Dictionary<string, UIGroup>();
            m_Serial = 0;
        }

        
        private void Start()
        {
            m_InstancePool = GameEntry.GetComponent<ObjectPoolManager>().CreatObjectPool<UIFormInstanceObject>("Instance.UIForm",ExpireTime,AutoReleaseTime);
            m_RecycleQueue = new Queue<IUIForm>();
            m_ResourceManager = GameEntry.GetComponent<ResourceManager>();
            if (UIRoot == null)
            {
                throw new GameFrameworkException("需要定义uiroot");
            }

            m_UIFormHelper = UIRoot.AddComponent<UIFormHelper>();
            
            if (GroupInfos.Length == 0)
            {
                throw new GameFrameworkException("需要定义uigroup");
            }
            
            foreach (var groupInfo in GroupInfos)
            {
                AddUIGroup(groupInfo.Name, groupInfo.Depth);
            }
        }

        /// <summary>
        /// 增加界面组。
        /// </summary>
        /// <param name="uiGroupName">界面组名称。</param>
        /// <param name="depth">界面组深度。</param>
        /// <returns>是否增加界面组成功。</returns>
        public bool AddUIGroup(string uiGroupName, int depth)
        {
            if (HasUIGroup(uiGroupName))
            {
                return false;
            }

            UIGroupHelper uiGroupHelper = new GameObject().AddComponent<UIGroupHelper>();
            if (uiGroupHelper == null)
            {
                Log.Error("Can not create UI group helper.");
                return false;
            }

            uiGroupHelper.name = string.Format("UI Group - {0}", uiGroupName);
            uiGroupHelper.gameObject.layer = LayerMask.NameToLayer("UI");
            Transform transform = uiGroupHelper.transform;
            transform.SetParent(UIRoot);
            transform.localScale = Vector3.one;

            var uiGroup = new UIGroup(uiGroupName, depth, uiGroupHelper);
            return m_UIGroups.TryAdd(uiGroupName,uiGroup);
        }

        

        private bool HasUIGroup(string uiGroupName)
        {
            return m_UIGroups.ContainsKey(uiGroupName);
        }

        /// <summary>
        /// 获取界面。
        /// </summary>
        /// <param name="serialId">界面序列编号。</param>
        /// <returns>要获取的界面。</returns>
        public IUIForm GetUIForm(int serialId)
        {
            foreach (KeyValuePair<string, UIGroup> uiGroup in m_UIGroups)
            {
                IUIForm uiForm = uiGroup.Value.GetUIForm(serialId);
                if (uiForm != null)
                {
                    return uiForm;
                }
            }

            return null;
        }

        /// <summary>
        /// 获取界面。
        /// </summary>
        /// <param name="uiFormAssetName">界面资源名称。</param>
        /// <returns>要获取的界面。</returns>
        public IUIForm GetUIForm(string uiFormAssetName)
        {
            if (string.IsNullOrEmpty(uiFormAssetName))
            {
                throw new GameFrameworkException("UI form asset name is invalid.");
            }

            foreach (KeyValuePair<string, UIGroup> uiGroup in m_UIGroups)
            {
                IUIForm uiForm = uiGroup.Value.GetUIForm(uiFormAssetName);
                if (uiForm != null)
                {
                    return uiForm;
                }
            }

            return null;
        }

        private bool IsLoadingUIForm(int serialId)
        {
            return m_UIFormsBeingLoaded.ContainsKey(serialId);
        }
        /// <summary>
        /// 是否正在加载界面。
        /// </summary>
        /// <param name="uiFormAssetName">界面资源名称。</param>
        /// <returns>是否正在加载界面。</returns>
        public bool IsLoadingUIForm(string uiFormAssetName)
        {
            if (string.IsNullOrEmpty(uiFormAssetName))
            {
                throw new GameFrameworkException("UI form asset name is invalid.");
            }

            return m_UIFormsBeingLoaded.ContainsValue(uiFormAssetName);
        }
        /// <summary>
        /// 获取界面。
        /// </summary>
        /// <param name="uiFormAssetName">界面资源名称。</param>
        /// <returns>要获取的界面。</returns>
        public IUIForm[] GetUIForms(string uiFormAssetName)
        {
            if (string.IsNullOrEmpty(uiFormAssetName))
            {
                throw new GameFrameworkException("UI form asset name is invalid.");
            }

            List<IUIForm> results = new List<IUIForm>();
            foreach (KeyValuePair<string, UIGroup> uiGroup in m_UIGroups)
            {
                results.AddRange(uiGroup.Value.GetUIForms(uiFormAssetName));
            }

            return results.ToArray();
        }
        private UIGroup GetUIGroup(string uiGroupName)
        {
            return m_UIGroups[uiGroupName];
        }

        public void CloseUIForm(int serialId, Object userData=null)
        {
            if (IsLoadingUIForm(serialId))
            {
                m_UIFormsToReleaseOnLoad.Add(serialId);
                m_UIFormsBeingLoaded.Remove(serialId);
                return;
            }

            var uiform= GetUIForm(serialId);
            if(uiform==null) return;
            CloseUIForm(uiform,userData);
        }


        /// <summary>
        /// 关闭界面。
        /// </summary>
        /// <param name="uiForm">要关闭的界面。</param>
        /// <param name="userData">用户自定义数据。</param>
        public void CloseUIForm(IUIForm uiForm, object userData)
        {
            if (uiForm == null)
            {
                throw new GameFrameworkException("UI form is invalid.");
            }

            IUIGroup uiGroup = (IUIGroup)uiForm.UIGroup;
            if (uiGroup == null)
            {
                throw new GameFrameworkException("UI group is invalid.");
            }

            uiGroup.RemoveUIForm(uiForm);
            uiForm.OnClose(userData);
            uiGroup.Refresh();

            /// 核心进入回收队列。
            m_RecycleQueue.Enqueue(uiForm);
        }
        private void InternalOpenUIForm(int serialId, string uiFormAssetName, IUIGroup uiGroup, object uiFormInstance, bool pauseCoveredUIForm, bool isNewInstance, float duration, object userData,UIOpenCallback callback)
        {
            try
            {
                IUIForm uiForm = m_UIFormHelper.CreateUIForm(uiFormInstance, uiGroup, userData);
                if (uiForm == null)
                {
                    callback?.Invoke(uiForm,false);
                    throw new GameFrameworkException("Can not create UI form in UI form helper.");
                }

                uiForm.OnInit(serialId, uiFormAssetName, uiGroup, pauseCoveredUIForm, isNewInstance, userData);
                uiGroup.AddUIForm(uiForm);
                uiForm.OnOpen(userData);
                //如何显示由uigroup决定
                uiGroup.Refresh();
                callback?.Invoke(uiForm,true);
            }
            catch (Exception exception)
            {
                throw;
            }
        }
        private void LoadAssetSuccessCallback(string uiFormAssetName, object uiFormAsset, object userData)
        {
            OpenUIFormInfo openUIFormInfo = (OpenUIFormInfo)userData;
            if (openUIFormInfo == null)
            {
                throw new GameFrameworkException("Open UI form info is invalid.");
            }

            if (m_UIFormsToReleaseOnLoad.Contains(openUIFormInfo.SerialId))
            {
                m_UIFormsToReleaseOnLoad.Remove(openUIFormInfo.SerialId);
                ReferencePool.Release(openUIFormInfo);
                m_UIFormHelper.ReleaseUIForm(uiFormAsset, null);
                return;
            }

            m_UIFormsBeingLoaded.Remove(openUIFormInfo.SerialId);
            /// 生成实例对象
            UIFormInstanceObject uiFormInstanceObject = UIFormInstanceObject.Create(uiFormAssetName, uiFormAsset, m_UIFormHelper);
            ///并在对象池中祖册他，当他需要销毁时，也需要通过对象池来销毁
            m_InstancePool.Register(uiFormInstanceObject, true);

            InternalOpenUIForm(openUIFormInfo.SerialId, uiFormAssetName, openUIFormInfo.UIGroup, uiFormInstanceObject.Target, openUIFormInfo.PauseCoveredUIForm, true, 0, openUIFormInfo.UserData,openUIFormInfo.Callback);
            ReferencePool.Release(openUIFormInfo);
        }
        /// <summary>
        /// 打开界面。
        /// </summary>
        /// <param name="uiFormAssetName">界面资源名称。</param>
        /// <param name="uiGroupName">界面组名称。</param>
        /// <param name="pauseCoveredUIForm">是否暂停被覆盖的界面。</param>
        /// <param name="userData">用户自定义数据。</param>
        /// <returns>界面的序列编号。</returns>
        public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm,
            object userData,UIOpenCallback callback=null)
        {
            
            if (m_ResourceManager == null)
            {
                throw new GameFrameworkException("You must set resource manager first.");
            }

            if (m_UIFormHelper == null)
            {
                throw new GameFrameworkException("You must set UI form helper first.");
            }

            if (string.IsNullOrEmpty(uiFormAssetName))
            {
                throw new GameFrameworkException("UI form asset name is invalid.");
            }

            if (string.IsNullOrEmpty(uiGroupName))
            {
                throw new GameFrameworkException("UI group name is invalid.");
            }

            UIGroup uiGroup = (UIGroup)GetUIGroup(uiGroupName);
            if (uiGroup == null)
            {
                throw new GameFrameworkException(string.Format("UI group '{0}' is not exist.", uiGroupName));
            }

            int serialId = ++m_Serial;
            ///尝试获得实例，
            UIFormInstanceObject uiFormInstanceObject = m_InstancePool.Spawn(uiFormAssetName);
            
            if (uiFormInstanceObject == null)
            {
                m_UIFormsBeingLoaded.Add(serialId, uiFormAssetName);
                m_ResourceManager.LoadAsset(uiFormAssetName, null, new LoadAssetCallback(LoadAssetSuccessCallback), OpenUIFormInfo.Create(serialId, uiGroup, pauseCoveredUIForm, userData,callback));
            }
            else
            {
                InternalOpenUIForm(serialId, uiFormAssetName, uiGroup, uiFormInstanceObject.Target, pauseCoveredUIForm, false, 0f, userData,callback);
            }

            return serialId;
        }
        public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
        {
            while (m_RecycleQueue.Count > 0)
            {
                IUIForm uiForm = m_RecycleQueue.Dequeue();
                uiForm.OnRecycle();
                m_InstancePool.Unspawn(uiForm.Handle);
            }

            foreach (KeyValuePair<string, UIGroup> uiGroup in m_UIGroups)
            {
                uiGroup.Value.OnUpdate(elapseSeconds, realElapseSeconds);
            }
        }

        public override void Shutdown()
        {
            // throw new NotImplementedException();
        }
    }

}